﻿package com.dusk.net
{
	import flash.desktop.NativeProcess;
	import flash.desktop.NativeProcessStartupInfo;
	import flash.filesystem.File;
	import flash.filesystem.FileMode;
	import flash.filesystem.FileStream;
	import flash.utils.ByteArray;
	
	//当程序处在Air下才可调用
	public class NativeFile
	{
		public static function exists(path:String):Boolean
		{
			return File.documentsDirectory.resolvePath(path).exists;
		}
		
		public static function write(content:*, path:String):Boolean
		{
			var file:File = File.documentsDirectory.resolvePath(path);
			var fileStream:FileStream = new FileStream();
			try
			{
				fileStream.open(file, FileMode.WRITE);
				if (content is String)
				{
					fileStream.writeUTFBytes(content);
				}
				else
				{
					fileStream.writeBytes(content);
				}
				fileStream.close();
				return true;
			} catch (e:Error)
			{
				fileStream.close();
				return false;
			}
		}
		
		public static function append(content:*, path:String):Boolean
		{
			var file:File = File.documentsDirectory.resolvePath(path);
			var fileStream:FileStream = new FileStream();
			try
			{
				fileStream.open(file, FileMode.APPEND);
				if (content is String)
				{
					fileStream.writeUTFBytes(content);
				}
				else
				{
					fileStream.writeBytes(content);
				}
				fileStream.close();
				return true;
			} catch (e:Error)
			{
				fileStream.close();
				return false;
			}
		}
		
		/**
		 * 读取文件
		 * @param path 文件路径
		 * @param readType 读取类型，可选值为"text"和"binary"
		 * @return 读取结果
		 */
		public static function read(path:String, readType:String = "text"):*
		{
			var file:File = File.documentsDirectory.resolvePath(path);
			var fileStream:FileStream = new FileStream();
			fileStream.open(file, FileMode.READ);
			if (readType == "binary")
			{
				var bytes:ByteArray = new ByteArray();
				fileStream.readBytes(bytes);
				fileStream.close();
				return bytes;
			}
			else if (readType == "text")
			{
				var str:String = fileStream.readUTFBytes(fileStream.bytesAvailable);
				fileStream.close();
				return str;
			}
			else
			{
				fileStream.close();
				return null;
			}
		}
		
		public static function createFolder(param1:String):void
		{
			var file:File = new File(param1);
			file.createDirectory();
		}
		
		public static function getAppRoot():String
		{
			return File.applicationDirectory.nativePath;
		}
		
		public static function getAppFolderFileUrl(param1:String):String
		{
			var _loc1_:String = File.applicationDirectory.nativePath;
			return _loc1_ + "/" + param1;
		}
		
		public static function move(sourceDir:String, targetDir:String, overwrite:Boolean = true):void
		{
			new File(sourceDir).moveTo(new File(targetDir), overwrite);
		}
		
		public static function copy(sourceDir:String, targetDir:String, overwrite:Boolean = true):void
		{
			new File(sourceDir).copyTo(new File(targetDir), overwrite);
		}
		
		public static function del(param1:String):void
		{
			try
			{
				new File(param1).deleteFile();
			}
			catch (e:Error)
			{
				trace(e);
			}
		}
		
		public static function rd(param1:String):void
		{
			new File(param1).deleteDirectory(true);
		}
		
		public static function start(path:String, ...args):void
		{
			//noinspection SpellCheckingInspection
			var NPSI:NativeProcessStartupInfo = new NativeProcessStartupInfo();
			NPSI.executable = File.documentsDirectory.resolvePath(path);
			NPSI.arguments = new Vector.<String>;
			while (args.length)
			{
				(NPSI.arguments as Vector.<String>).push(args.shift());
			}
			trace(NPSI.executable.nativePath)
			var NP:NativeProcess = new NativeProcess();
			NP.start(NPSI);
		}
		
		/**
		 * 获取目标文件在指定目录的深度，最多到100层
		 * @param curFile 当前文件或者文件夹
		 * @param targetDir 目标目录（不能说文件）
		 * @return 返回1则表示是该文件夹内的子文件或者子文件夹，以此类推
		 * @return 若返回-1则表示不是该文件夹内的子文件或者子文件夹或者层数超出最大限制100层
		 * @example
		 * file1 = new File("test/");
		 * file2 = new File("test/test");
		 * file3 = new File("test/test/test.txt");
		 * file4 = new File("exception/");
		 * trace(getDepthFileToTarget(file2,file1));
		 * //输出：1
		 * trace(getDepthFileToTarget(file3,file1));
		 * //输出：2
		 * trace(getDepthFileToTarget(file4,file1));
		 * //输出：-1
		 */
		public static function getFileDepthInTargetDir(curFile:File, targetDir:File):int
		{
			if(!targetDir.isDirectory) return -1;
			for(var i:int = 1; i <= 100; i++)
			{
				if(curFile.parent.nativePath == targetDir.nativePath)
				{
					return i;
				}
			}
			return -1;
		}
		
		/**
		 * 获取文件夹下所有文件，不包括文件夹
		 * @param folder 目标目录
		 * @param depth 搜索深度
		 * @return 文件列表
		 */
		public static function getAllFilesInFolder(folder:File, depth:int = 999):Vector.<File>
		{
			var folderQueue:Vector.<File> = new Vector.<File>();
			var fileList:Vector.<File> = new Vector.<File>();
			if (!folder.isDirectory) return new Vector.<File>();
			var folderTmp:File = new File(folder.nativePath);
			folderQueue.push(folderTmp);
			while (!folderQueue.isEmpty())
			{
				folderTmp = folderQueue.shift();
				if (!folderTmp.exists || folderTmp.getDirectoryListing().isEmpty()) continue;
				folderTmp.getDirectoryListing().forEach(function (item:File, a:*, b:*):void
				{
					if (item.isDirectory)
					{
						if (getFileDepthInTargetDir(item,folder) < depth)
						{
							folderQueue.push(item);
						}
					}
					else
					{
						fileList.push(item);
					}
				});
			}
			return fileList;
		}
	}
}